Req.prototype.constructor = Req;

/**
 *	@class
 *	Req é uma classe que gerencia as requisições feitas no backend.
 *	Ela realiza a chamada através de Ext.Ajax.request e trata seu retorno.
 *	IMPORTANTE: Se você for herdar esta classe, tome cuidado com o construtor
 *	<b>init()</b>, pois nesta classe ele é chamado implicitamente.
 *	@see Req#init
 */
function Req (args) {
	this.reqDefCallbackExecd = false;
	this.suppressSuccess = false;
	this.url = DEF_REQ_URL;

	/**
		Este método trata os parâmetros e faz a chamada no backend
		@param reqObj Objeto requisitante, o qual será o executor do callback
		@param params Parâmetros que devem ser passados para o backend
		@param oper Nome da operação registrada no Ctrl
		@param type Tipo do evento (SYNC, ASYNC_IGNR E ASYNC_MNGD)
	*/
	this.init = function (args) {
		this.reqObj = args.reqObj;
		this.params = args.params;
		this.oper = args.oper;

		if (args.type)
			this.type = args.type;
		else
			this.type = NAME_REQ_TYPE_SYNC;

		this.params.oper = this.reqObj[this.oper].name;

		if (this.type == NAME_REQ_TYPE_ASYNC_MNGD)
			this.suppressSuccess = true;

		if (this.type == NAME_REQ_TYPE_ASYNC_IGNR || this.type == NAME_REQ_TYPE_ASYNC_MNGD)
			this.reqCallback (true, null);
	}

	/**
	 *	Autoriza a ida da requisição para o backend
	 */
	this.go = function () {
		this.reqId = Ext.Ajax.request ({
			url       : this.url
			,callback : this.ajaxCallback
			,scope    : this
			,jsonData : this.params
		});
	}

	/**
	 *	Método executado como callback da requisição
	 *	É executado independentemente de ser síncrono ou assíncrono.
	 *	@param success Booleano indicando se sucesso é verdadeiro
	 *	@param data Dados retornados pela requisição para o solicitante
	 */
	this.reqCallback = function (success, data) {
		if (this.reqObj.oper[this.oper].callback && !this.reqDefCallbackExecd) {
			this.reqObj.oper[this.oper].callback.call (this.reqObj, {data: data});
			this.reqDefCallbackExecd = true;
		}

		if (success) {
			if (this.reqObj.oper[this.oper].success && !this.suppressSuccess) {
				this.reqObj.oper[this.oper].success.call (this.reqObj, {data: data});
				this.suppressSuccess = false;
			}
		}
		else {
			if (this.reqObj.oper[this.oper].failure)
				this.reqObj.oper[this.oper].failure.call (this.reqObj, {data: data});
		}
	}

	/**
	 *	Método executado no retorno da requisição no backend
	 *	Nos casos de requisição assíncrona, o requisitante pode receber uma resposta
	 *	positiva inicialmente, depois receber a falha do backend, caso tenha interesse.
	 *	Os parâmetros são implementados por Ext.Ajax.request
	 */
	this.ajaxCallback = function (options, success, response) {
		var data = null;

		if (response.responseText)
			data = Ext.util.JSON.decode (response.responseText);
		else
			data = response;

		if (this.type == NAME_REQ_TYPE_ASYNC_IGNR) {
			if (!success)
				this.reqCallback (success, data)
			return;
		}

		if (this.type == NAME_REQ_TYPE_ASYNC_MNGD) {
			// TODO: instanciar um objeto que controle esta requisição posteriormente
			return;
		}

		this.reqCallback (success, data);
	}

	this.init (args);
}
